package com.igd.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.igd.security.Roles;

 /**
 * @version  1.0
 *
 * @author   QIAOYU
 *
 * @date     2013-6-27
 *
 * @description	 反射公共工具类
 */

public class ReflectionUtil {

	private static Logger logger = Logger.getLogger(ReflectionUtil.class);
	
	/**
	 * 将对象属性以及属性值转换为Map对象
	 * 
	 * @param clz Class类型
	 * 
	 * @param o 要转换为Map的对象实例
	 * 
	 * @return Map<String,Object>
	 * 
	 * @throws ClassNotFoundException
	 * 
	 * @throws SecurityException
	 * 
	 * @throws IllegalArgumentException
	 * 
	 * @throws IllegalAccessException
	 * 
	 * @throws InvocationTargetException
	 */
	public static Map<String,String> objectToMap(Class<?> clz,Object o) throws ClassNotFoundException, SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException{
		
		Field[] fields = getFieldsWithSuper(clz);
		
		if(null != fields){
			
			Map<String,String> map = new HashMap<String,String>(fields.length);

			for(Field f : fields){
				
				String fieldName = f.getName().trim();
				
				String methodName = CommonUtil.createGetMethodName(fieldName);
				
				Method method = null;
				
				try {
					
					method = getMethod(clz,methodName,new Class[]{});
					
					if(null != method){
						
						Object val = methodInvoke(method,o,new Object[]{});
						
						if(null != val){
							
							map.put(fieldName,CommonUtil.getNullString(val));
							
						}
					}
					
				} catch (NoSuchMethodException e) {
					
					logger.error(clz.getName() + " has no method named " + methodName);

				}
			}
			
			return map;
		}
		
		return null;
	}
	
	/**
	 * 获取类文件所有的字段信息
	 * 
	 * @param clz
	 * 
	 * @return Field[]
	 */
	public static Field[] getFields(Class<?> clz){
		
		return clz !=null ? clz.getDeclaredFields() : null;

	}
	
	/**
	 * 获取当前类文件以及超类的字段信息
	 * 
	 * @param clz
	 * 
	 * @return Field[]
	 */
	public static Field[] getFieldsWithSuper(Class<?> clz){
		
		Field [] currentClz = getFields(clz);
		
		Class<?> sClz = clz.getSuperclass();
		
		if(null != sClz && null != currentClz){
			
			Field [] superClz = getFields(sClz);
			
			if(null != superClz){
				
				Field [] res = new Field[currentClz.length + superClz.length];
				
				System.arraycopy(currentClz,0, res,0,currentClz.length);
				
				System.arraycopy(superClz,0, res,currentClz.length,res.length - currentClz.length);
				
				return res;
				
			}else{
				
				return currentClz;

			}
		}
		
		return null;
	}
	
	/**
	 * 获取类文件所有的方法
	 * 
	 * @param clz
	 * 
	 * @return Method []
	 */
	public static Method [] getMethods(Class<?> clz){
		
		return clz != null ? clz.getMethods() : null;
	}
	
	/**
	 * 根据指定的方法名与参数类型获取指定的方法
	 * 
	 * @param clz
	 * 
	 * @param mName
	 * 
	 * @param parameterTypes
	 * 
	 * @return Method
	 * 
	 * @throws SecurityException
	 * 
	 * @throws NoSuchMethodException
	 */
	public static Method getMethod(Class<?> clz,String mName,Class<?>...parameterTypes) throws SecurityException, NoSuchMethodException{
		
		return null != clz && StringUtils.isNotEmpty(mName) && null != parameterTypes ? clz.getMethod(mName, parameterTypes) : null;
	}
	
	/**
	 * 判断类文件中是否存在指定字段
	 * 
	 * @param clz
	 * 
	 * @param fieldName
	 * 
	 * @return Field
	 */
	public static Field hasField(Class<?> clz,String fieldName){
		
		if(null != clz && StringUtils.isNotEmpty(fieldName)){
			
			Field [] field  = getFields(clz);
			
			for(Field f : field){

				if(f.getName().equals(fieldName)){

					return f;

				}
			}
		}
		
		return null;
	}
	
	/**
	 * 调用传入的指定的方法
	 * 
	 * @param method 传入方法
	 * 
	 * @param obj 目标对象,调用方法的实例对象
	 * 
	 * @param args 调用的方法对应参数
	 * 
	 * @return
	 * 
	 * @throws IllegalArgumentException
	 * 
	 * @throws IllegalAccessException
	 * 
	 * @throws InvocationTargetException
	 */
	public static Object methodInvoke(Method method,Object obj,Object...args) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{

		return null != method && null != obj ? method.invoke(obj, args) : null;

	}
}
